home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / lang / sofa.lha / sofa / smalleiffel / lib_se / switch.e < prev    next >
Text File  |  2000-03-25  |  14KB  |  456 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr
  4. --                       http://SmallEiffel.loria.fr
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License
  11. -- for  more  details.  You  should  have  received a copy of the GNU General
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. expanded class SWITCH
  17.    --
  18.    -- Set of tools (no attributes) to handle one switching site.
  19.    --
  20.  
  21. inherit GLOBALS;
  22.  
  23. feature {NONE}
  24.  
  25.    running: ARRAY[RUN_CLASS] is
  26.          -- The global one.
  27.       once
  28.          !!Result.with_capacity(256,1);
  29.       end;
  30.  
  31. feature
  32.  
  33.    c_define(up_rf: RUN_FEATURE) is
  34.          -- Define the switching C function for `up_rf'.
  35.       require
  36.          cpp.on_c
  37.       local
  38.          boost: BOOLEAN;
  39.          arguments:  FORMAL_ARG_LIST;
  40.          result_type, arg_type: TYPE;
  41.          i: INTEGER;
  42.       do
  43.          boost := run_control.boost;
  44.          arguments := up_rf.arguments;
  45.          result_type := up_rf.result_type;
  46.          c_code.clear;
  47.          if result_type = Void then
  48.             c_code.append(fz_void);
  49.          else
  50.             result_type := result_type.run_type;
  51.             result_type.c_type_for_result_in(c_code);
  52.          end;
  53.          c_code.extend(' ');
  54.          c_code.extend('X');
  55.          up_rf.current_type.id.append_in(c_code);
  56.          up_rf.name.mapping_c_in(c_code);
  57.          if boost then
  58.             c_code.append("(T0*C");
  59.          else
  60.             c_code.append("(se_dump_stack*caller,se_position position,T0*C");
  61.          end;
  62.          if arguments /= Void then
  63.             from
  64.                i := 1;
  65.             until
  66.                i > arguments.count
  67.             loop
  68.                c_code.extend(',');
  69.                arg_type := arguments.type(i).run_type;
  70.                arg_type.c_type_for_argument_in(c_code);
  71.                c_code.append(" a");
  72.                i.append_in(c_code);
  73.                i := i + 1;
  74.             end;
  75.          end;
  76.          c_code.extend(')');
  77.          cpp.put_c_heading(c_code);
  78.          cpp.swap_on_c;
  79.          if result_type /= Void then
  80.             c_code.clear;
  81.             result_type.c_type_for_result_in(c_code);
  82.             c_code.extend(' ');
  83.             c_code.extend('R');
  84.             if not boost then
  85.                c_code.extend('=');
  86.                result_type.c_initialize_in(c_code);
  87.             end;
  88.             c_code.append(fz_00);
  89.             cpp.put_string(c_code);
  90.          end;
  91.          if not boost then
  92.             cpp.put_string("se_dump_stack ds=*caller;%N%
  93.                            %ds.caller=caller;%N");
  94.          end;
  95.          cpp.put_string("{Tid id=");
  96.          running.copy(up_rf.current_type.run_class.running);
  97.          sort_running(running);
  98.          if boost then
  99.             cpp.put_string("((T0*)C)->id;%N");
  100.          else
  101.             cpp.put_string("vc(C,position)->id;%N");
  102.          end;
  103.          if run_control.all_check then
  104.             c_switch(up_rf);
  105.          else
  106.             c_dicho(up_rf,1,running.upper);
  107.          end;
  108.          cpp.put_string(fz_12);
  109.          if not boost then
  110.             cpp.put_string("se_dst=caller;%N");
  111.          end;
  112.          if result_type /= Void then
  113.             cpp.put_string(fz_15);
  114.          else
  115.             cpp.put_string(fz_12);
  116.          end;
  117.          cpp.finished_switch(running.upper);
  118.       ensure
  119.          cpp.on_c
  120.       end;
  121.  
  122. feature {C_PRETTY_PRINTER}
  123.  
  124.    put_arguments(up_rf: RUN_FEATURE; fal: FORMAL_ARG_LIST) is
  125.          -- Produce C code for arguments of `fal' used
  126.          -- inside the switching C function.
  127.       require
  128.          cpp.on_c;
  129.          fal.count = up_rf.arguments.count
  130.       local
  131.          i, up: INTEGER;
  132.       do
  133.          from
  134.             i := 1;
  135.             up := fal.count;
  136.          until
  137.             i > up
  138.          loop
  139.             if i > 1 then
  140.                cpp.put_character(',');
  141.             end;
  142.             put_ith_argument(up_rf,fal,i);
  143.             i := i + 1;
  144.          end;
  145.       ensure
  146.          cpp.on_c
  147.       end;
  148.  
  149.    put_ith_argument(up_rf: RUN_FEATURE; fal: FORMAL_ARG_LIST; index: INTEGER) is
  150.          -- Produce C code for argument `index' of `fal' used
  151.          -- inside the switching C function.
  152.       require
  153.          cpp.on_c;
  154.          fal.count = up_rf.arguments.count;
  155.          1 <= index;
  156.          index <= fal.count
  157.       local
  158.          eal: like fal;
  159.          at, ft: TYPE;
  160.       do
  161.          eal := up_rf.arguments;
  162.          at := eal.type(index).run_type;
  163.          ft := fal.type(index).run_type;
  164.          if at.is_reference and then ft.is_basic_eiffel_expanded then
  165.             cpp.put_character('(');
  166.             ft.cast_to_ref;
  167.             cpp.put_character('a');
  168.             cpp.put_integer(index);
  169.             cpp.put_string(")->_item");
  170.          else
  171.             cpp.put_character('a');
  172.             cpp.put_integer(index);
  173.          end;
  174.       ensure
  175.          cpp.on_c
  176.       end;
  177.  
  178. feature {NONE}
  179.  
  180.    c_dicho(up_rf: RUN_FEATURE; bi, bs: INTEGER) is
  181.          -- Produce dichotomic inspection code for Current id.
  182.       require
  183.          bi <= bs
  184.       local
  185.          m: INTEGER;
  186.          dyn_rc: RUN_CLASS;
  187.          dyn_rf: RUN_FEATURE;
  188.       do
  189.          if bi = bs then
  190.             dyn_rc := running.item(bi);
  191.             dyn_rf := dyn_rc.dynamic(up_rf);
  192.             cpp.inside_switch_call(dyn_rf,up_rf);
  193.          else
  194.             m := (bi + bs) // 2;
  195.             dyn_rc := running.item(m);
  196.             cpp.put_string("if(id<=");
  197.             cpp.put_integer(dyn_rc.id);
  198.             cpp.put_string("){%N");
  199.             c_dicho(up_rf,bi,m);
  200.             cpp.put_string("}%Nelse{%N");
  201.             c_dicho(up_rf,m + 1,bs);
  202.             cpp.put_character('}');
  203.          end;
  204.       end;
  205.  
  206.    c_switch(up_rf: RUN_FEATURE) is
  207.          -- Produce C switch inspection code for Current id.
  208.       local
  209.          i: INTEGER;
  210.          dyn_rc: RUN_CLASS;
  211.          dyn_rf: RUN_FEATURE;
  212.       do
  213.          cpp.put_string("switch(id){%N");
  214.          from
  215.             i := 1;
  216.          until
  217.             i > running.upper
  218.          loop
  219.             dyn_rc := running.item(i);
  220.             dyn_rf := dyn_rc.dynamic(up_rf);
  221.             cpp.put_string("case ");
  222.             cpp.put_integer(dyn_rc.id);
  223.             cpp.put_character(':');
  224.             cpp.inside_switch_call(dyn_rf,up_rf);
  225.             cpp.put_string("%Nbreak;%N");
  226.             i := i + 1;
  227.          end;
  228.          if run_control.no_check then
  229.             cpp.put_string("default: error2(C,position);%N");
  230.          end;
  231.          cpp.put_string(fz_12);
  232.       end;
  233.  
  234. feature {C_PRETTY_PRINTER,SWITCH}
  235.  
  236.    name(up_rf: RUN_FEATURE): STRING is
  237.       do
  238.          c_code.clear;
  239.          c_code.extend('X');
  240.          up_rf.current_type.id.append_in(c_code);
  241.          c_code.append(up_rf.name.to_key);
  242.          Result := c_code;
  243.       end;
  244.  
  245. feature
  246.  
  247.    jvm_descriptor(up_rf: RUN_FEATURE): STRING is
  248.       local
  249.          arguments:  FORMAL_ARG_LIST;
  250.          rt: TYPE;
  251.       do
  252.          arguments := up_rf.arguments;
  253.          tmp_jvmd.clear;
  254.          tmp_jvmd.extend('(');
  255.          tmp_jvmd.append(jvm_root_descriptor);
  256.          if arguments /= Void then
  257.             arguments.jvm_descriptor_in(tmp_jvmd);
  258.          end;
  259.          rt := up_rf.result_type;
  260.          if rt = Void then
  261.             tmp_jvmd.append(fz_19);
  262.          else
  263.             rt := rt.run_type;
  264.             tmp_jvmd.extend(')');
  265.             if rt.is_reference then
  266.                tmp_jvmd.append(jvm_root_descriptor);
  267.             else
  268.                rt.jvm_descriptor_in(tmp_jvmd);
  269.             end;
  270.          end;
  271.          Result := tmp_jvmd;
  272.       end;
  273.  
  274. feature {NONE}
  275.  
  276.    tmp_jvmd: STRING is
  277.       once
  278.          !!Result.make(32);
  279.       end;
  280.  
  281. feature
  282.  
  283.    idx_methodref(up_rf: RUN_FEATURE): INTEGER is
  284.       require
  285.          up_rf /= Void
  286.       do
  287.          Result := constant_pool.idx_methodref3(jvm_root_class,
  288.                                                 name(up_rf),
  289.                                                 jvm_descriptor(up_rf));
  290.       end;
  291.  
  292. feature {JVM}
  293.  
  294.    jvm_mapping(cpc: CALL_PROC_CALL) is
  295.       require
  296.          cpc /= Void
  297.       local
  298.          idx, stack_level: INTEGER;
  299.          up_rf: RUN_FEATURE;
  300.          target: EXPRESSION;
  301.          eal: EFFECTIVE_ARG_LIST;
  302.          fal: FORMAL_ARG_LIST;
  303.          switch: SWITCH;
  304.       do
  305.          target := cpc.target;
  306.          up_rf := cpc.run_feature;
  307.          eal := cpc.arguments;
  308.          target.compile_to_jvm;
  309.          stack_level := 1;
  310.          if eal /= Void then
  311.             fal := up_rf.arguments;
  312.             stack_level := stack_level + eal.compile_to_jvm(fal);
  313.          end;
  314.          if up_rf.result_type /= Void then
  315.             stack_level := stack_level - up_rf.result_type.jvm_stack_space;
  316.          end;
  317.          idx := switch.idx_methodref(up_rf);
  318.          code_attribute.opcode_invokestatic(idx,-stack_level);
  319.       end;
  320.  
  321. feature {SWITCH_COLLECTION}
  322.  
  323.    afd(up_rf: RUN_FEATURE) is
  324.       local
  325.          r: ARRAY[RUN_CLASS];
  326.          i: INTEGER;
  327.          x_result_type, r_result_type: TYPE;
  328.          x_current_type, r_current_type: TYPE;
  329.          dyn_rf: RUN_FEATURE;
  330.          x_arguments, r_arguments: FORMAL_ARG_LIST;
  331.       do
  332.          x_current_type := up_rf.current_type;
  333.          x_result_type := up_rf.result_type;
  334.          x_arguments := up_rf.arguments;
  335.          from
  336.             r := up_rf.current_type.run_class.running;
  337.             i := r.upper;
  338.          until
  339.             i = 0
  340.          loop
  341.             dyn_rf := r.item(i).dynamic(up_rf);
  342.             r_current_type := dyn_rf.current_type;
  343.             conversion_handler.passing(x_current_type,r_current_type);
  344.             if x_result_type /= Void then
  345.                r_result_type := dyn_rf.result_type;
  346.                conversion_handler.passing(r_result_type,x_result_type);
  347.             end;
  348.             if x_arguments /= Void then
  349.                r_arguments := dyn_rf.arguments;
  350.                x_arguments.afd_notify_conversion(r_arguments);
  351.             end;
  352.             i := i - 1;
  353.          end;
  354.       end;
  355.  
  356.    jvm_define(up_rf: RUN_FEATURE) is
  357.       local
  358.          rt: TYPE;
  359.       do
  360.          -- Define the Java switching static method for `up_rf'.
  361.          method_info.start(9,name(up_rf),jvm_descriptor(up_rf));
  362.          running.copy(up_rf.current_type.run_class.running);
  363.          rt := up_rf.result_type;
  364.          if rt /= Void then
  365.             rt := rt.run_type;
  366.          end;
  367.          jvm_switch(up_rf,rt);
  368.          method_info.finish;
  369.       end;
  370.  
  371. feature {NONE}
  372.  
  373.    c_code: STRING is
  374.       once
  375.          !!Result.make(256);
  376.       end;
  377.  
  378. feature {NONE}
  379.  
  380.    jvm_switch(up_rf: RUN_FEATURE; rt: TYPE) is
  381.          -- Produce Java sequential switch code.
  382.       require
  383.          rt /= Void implies rt.run_type = rt
  384.       local
  385.          space, point, i: INTEGER;
  386.          dyn_rc: RUN_CLASS;
  387.          dyn_rf: RUN_FEATURE;
  388.          boost: BOOLEAN;
  389.          ca: like code_attribute;
  390.          static_na, dynamic_na: TYPE_NATIVE_ARRAY;
  391.       do
  392.          ca := code_attribute;
  393.          from
  394.             boost := run_control.boost;
  395.             i := running.upper;
  396.          until
  397.             i = 0
  398.          loop
  399.             dyn_rc := running.item(i);
  400.             dyn_rf := dyn_rc.dynamic(up_rf);
  401.             if i = 1 and then boost then
  402.             else
  403.                ca.opcode_aload_0;
  404.                dyn_rf.run_class.opcode_instanceof;
  405.                point := ca.opcode_ifeq;
  406.             end;
  407.             jvm.push_switch(dyn_rf,up_rf);
  408.             dyn_rf.mapping_jvm;
  409.             jvm.pop;
  410.             if rt = Void then
  411.                ca.opcode_return;
  412.             elseif rt.is_native_array then
  413.                static_na ?= rt.run_type;
  414.                dynamic_na ?= dyn_rf.result_type.run_type;
  415.                if static_na.run_time_mark = dynamic_na.run_time_mark then
  416.                   static_na.jvm_return_code;
  417.                elseif static_na.of_references and then dynamic_na.of_references then
  418.                   static_na.jvm_return_code;
  419.                else
  420.                   if run_control.no_check then
  421.                      ca.runtime_error(up_rf.start_position,up_rf.current_type,
  422.                      "System-level Validity error detected inside virtual %
  423.                      %switching code.%N%
  424.                      %Bad NATIVE_ARRAY type return type.");
  425.                   end;
  426.                   ca.opcode_pop;
  427.                   space := rt.jvm_push_default;
  428.                   rt.jvm_return_code;
  429.                end;
  430.             else
  431.                space := dyn_rf.result_type.jvm_convert_to(rt);
  432.                rt.jvm_return_code;
  433.             end;
  434.             if i = 1 and then boost then
  435.             else
  436.                ca.resolve_u2_branch(point);
  437.             end;
  438.             i := i - 1;
  439.          end;
  440.          if not boost then
  441.             ca.opcode_aload_0;
  442.             ca.runtime_error_bad_target(up_rf.start_position,up_rf.current_type,
  443.                "System-level Validity error detected inside virtual %
  444.                %switching code.%N%
  445.                %Bad target type for dynamic dispatch.");
  446.             if rt = Void then
  447.                ca.opcode_return;
  448.             else
  449.                space := rt.jvm_push_default;
  450.                rt.jvm_return_code;
  451.             end;
  452.          end;
  453.       end;
  454.  
  455. end
  456.